
#import serial
import time
import struct
from Crc import ModbusCrc
#from ModbusRTU import CModbus

class CFastScopeComm():

    def __init__(self, port, chList, xAxies):

        self.port = port
        self.chList = chList
        self.xAxies = xAxies
        self.chCount = 0
        self.frameSize = 0
        self.startTime = time.clock()
        self.prevTime = self.startTime
        self.count = 0
        self.span = 0.00025

    def Start(self):
        
        self.chCount = 0
        self.frameSize = 0
        self.count = 0
        
        Data = bytearray()
        for ch in self.chList:
            
            if ch.active:
                
                frameSize = 1 << ch.size                
                addr = ch.addr + (ch.size << 30)
            
                Data.append(addr & 0xFF)
                Data.append((addr >> 8) & 0xFF)
                Data.append((addr >> 16) & 0xFF)
                Data.append((addr >> 24) & 0xFF)
                self.chCount = self.chCount + 1
                self.frameSize = self.frameSize + frameSize

        # Add checksum bytes
        self.frameSize = self.frameSize + 2


        crc = ModbusCrc.Calc(Data)
        Data.append(crc & 0xFF)
        Data.append(crc >> 8)

        count = len(Data)
        
        self.port.flushInput()

        index = 0
        while index < count:
            if count - index > 8:
                self.port.write(Data[index: index + 8])
                index = index + 8
            else:
                self.port.write(Data[index: count])
                index = count

            time.sleep(0.05)
            
        self.startTime = time.clock()
        self.prevTime = self.startTime
        

    def GetData(self):

        size = self.port.inWaiting()

        # Read integer times of a frame size
        size = size -size%self.frameSize

        data = self.port.read(size)

        dataIndex = 0

        while dataIndex < size:

            crc = ModbusCrc.Calc(data[dataIndex: dataIndex + self.frameSize - 2])
            crc2 = (data[dataIndex + self.frameSize - 1] << 8) + data[dataIndex + self.frameSize - 2]

            if crc == crc2:

                #chIndex = 0
                offset = 0
                for dataCh in self.chList:
                    # Skip invalid channel
                    if not dataCh.active:
                        continue
                        
                    if dataCh.type == 'Float':
                        byteCount = 4
                        fmt = '<f'
                    elif dataCh.size == 2:
                        byteCount = 4
                        if dataCh.type == 'Uint':
                            fmt = '<I'
                        else:
                            fmt = '<i'
                            
                    elif dataCh.size == 1:
                        byteCount = 2
                        if dataCh.type == 'Uint':
                            fmt = '<H'
                        else:
                            fmt = '<h'
                        
                    elif dataCh.size == 1:
                        byteCount = 2
                        if dataCh.type == 'Uint':
                            fmt = '<B'
                        else:
                            fmt = '<b'
                        
                    datum = struct.unpack(fmt, data[dataIndex + offset: dataIndex + offset + byteCount])[0]
                    offset = offset + byteCount                        

                    datum = datum * dataCh.scale + dataCh.offset
                    dataCh.append(datum)
                    
                self.count = self.count + 1
                self.xAxies.append(self.count*self.span)

            dataIndex = dataIndex + self.frameSize
            
            


class CSlowScopeComm:

    def __init__(self, protocol, dataList, xAxies):
        
        self.protocol = protocol
        self.dataList = dataList
        self.xAxies = xAxies
        self.startTime = time.clock()
        
        
    def Start(self):
        self.startTime = time.clock()
        
    def GetData(self):
        
        for ch in self.dataList:
            
            if not ch.active:
                continue
            
            self.protocol.SetDeviceAddr(ch.slaveAddr)  
            
            if ch.isParam:                

                addr = ch.addr
                if ch.size == 2 or ch.type == 'Float':
                    addr = addr + 0x8000
                err, value = self.protocol.Read(addr)
                
                if err == 0: 
 
                    value = value[0]
                    
                    if ch.type == 'Float':
                        bytes = struct.pack('>I', value)
                        value = struct.unpack('>f', bytes)
                    
                    elif ch.type == 'Int':
                        
                        if ch.size == 1 and value > 32767:
                            value = value - 65536
                        elif ch.size == 2 and value > (1 << 31) - 1:
                            value = value - (1 << 32)
                        
                    value = value * ch.scale + ch.offset
                    ch.append(value)
                    
                
            else:
                
                type = 1
                
                if ch.size == 'n32':
                    type = 2
                elif ch.size == 'f32':
                    type = 3
                
                err, value = self.protocol.FFReadMem(ch.addr, type, 1)
                
                if err == 0: 
 
                    value = value[0]
                    
                    if ch.sign == 'S':
                        
                        if ch.size == 'n16' and value > 32767:
                            value = value - 65536
                        elif ch.size == 'n32' and value > (1 << 31) - 1:
                            value = value - (1 << 32)
                    
                    value = value * ch.scale + ch.offset                        
                    ch.append(value)
        
        self.xAxies.append(time.clock() - self.startTime)
